#ifndef _WX_UTILSH__
#define _WX_UTILSH__

#include "wx/object.h"
#include "wx/list.h"
#include "wx/filefn.h"
#if wxUSE_GUI
#include "wx/gdicmn.h"
#endif

class wxArrayString;
class wxArrayInt;

#include "wx/longlong.h"
#include "wx/platinfo.h"

#ifdef __WATCOMC__
#include <direct.h>
#elif defined(__X__)
#include <dirent.h>
#include <unistd.h>
#endif

#include <stdio.h>

class wxProcess;
class wxFrame;
class wxWindow;
class wxWindowList;

#define wxMax(a,b)            (((a) > (b)) ? (a) : (b))
#define wxMin(a,b)            (((a) < (b)) ? (a) : (b))
#define wxClip(a,b,c)         (((a) < (b)) ? (b) : (((a) > (c)) ? (c) : (a)))

#if wxUSE_LONGLONG
typedef wxLongLong wxMemorySize;
#else
typedef long wxMemorySize;
#endif

void wxBell();
wxString wxGetOsDescription();
wxOperatingSystemId wxGetOsVersion( int *majorVsn = ( int * ) NULL, int *minorVsn = ( int * ) NULL );
bool wxIsPlatformLittleEndian();
bool wxIsPlatform64Bit();
wxString wxNow();
const wxChar *wxGetInstallPrefix();
wxString wxGetDataDir();

class wxPlatform {
  public:
    wxPlatform() { Init(); }
    wxPlatform( const wxPlatform& platform ) { Copy( platform ); }
    void operator = ( const wxPlatform& platform ) { Copy( platform ); }
    void Copy( const wxPlatform& platform );
    wxPlatform( int defValue ) { Init(); m_longValue = ( long )defValue; }
    wxPlatform( long defValue ) { Init(); m_longValue = defValue; }
    wxPlatform( const wxString& defValue ) { Init(); m_stringValue = defValue; }
    wxPlatform( double defValue ) { Init(); m_doubleValue = defValue; }
    static wxPlatform If( int platform, long value );
    static wxPlatform IfNot( int platform, long value );
    wxPlatform& ElseIf( int platform, long value );
    wxPlatform& ElseIfNot( int platform, long value );
    wxPlatform& Else( long value );
    static wxPlatform If( int platform, int value ) { return If( platform, ( long )value ); }
    static wxPlatform IfNot( int platform, int value ) { return IfNot( platform, ( long )value ); }
    wxPlatform& ElseIf( int platform, int value ) { return ElseIf( platform, ( long ) value ); }
    wxPlatform& ElseIfNot( int platform, int value ) { return ElseIfNot( platform, ( long ) value ); }
    wxPlatform& Else( int value ) { return Else( ( long ) value ); }
    static wxPlatform If( int platform, double value );
    static wxPlatform IfNot( int platform, double value );
    wxPlatform& ElseIf( int platform, double value );
    wxPlatform& ElseIfNot( int platform, double value );
    wxPlatform& Else( double value );
    static wxPlatform If( int platform, const wxString& value );
    static wxPlatform IfNot( int platform, const wxString& value );
    wxPlatform& ElseIf( int platform, const wxString& value );
    wxPlatform& ElseIfNot( int platform, const wxString& value );
    wxPlatform& Else( const wxString& value );
    long GetInteger() const { return m_longValue; }
    const wxString& GetString() const { return m_stringValue; }
    double GetDouble() const { return m_doubleValue; }
    operator int() const { return ( int ) GetInteger(); }
    operator long() const { return GetInteger(); }
    operator double() const { return GetDouble(); }
    operator const wxString() const { return GetString(); }
    operator const wxChar*() const { return ( const wxChar* ) GetString(); }
    static void AddPlatform( int platform );
    static bool Is( int platform );
    static void ClearPlatforms();
  private:
    void Init() { m_longValue = 0; m_doubleValue = 0.0; }
    long                m_longValue;
    double              m_doubleValue;
    wxString            m_stringValue;
    static wxArrayInt*  sm_customPlatforms;
};

inline bool wxPlatformIs( int platform ) { return wxPlatform::Is( platform ); }

#if wxUSE_GUI

bool wxGetKeyState( wxKeyCode key );
bool wxSetDetectableAutoRepeat( bool flag );

class wxMouseState {
  public:
    wxMouseState()
      : m_x( 0 ), m_y( 0 ),
        m_leftDown( false ), m_middleDown( false ), m_rightDown( false ),
        m_controlDown( false ), m_shiftDown( false ), m_altDown( false ),
        m_metaDown( false ) {}
    wxCoord     GetX() { return m_x; }
    wxCoord     GetY() { return m_y; }
    bool        LeftDown()    { return m_leftDown; }
    bool        MiddleDown()  { return m_middleDown; }
    bool        RightDown()   { return m_rightDown; }
    bool        LeftIsDown()    { return m_leftDown; }
    bool        MiddleIsDown()  { return m_middleDown; }
    bool        RightIsDown()   { return m_rightDown; }
    bool        ControlDown() { return m_controlDown; }
    bool        ShiftDown()   { return m_shiftDown; }
    bool        AltDown()     { return m_altDown; }
    bool        MetaDown()    { return m_metaDown; }
    bool        CmdDown() {
      #if defined(__WXMAC__) || defined(__WXCOCOA__)
      return MetaDown();
      #else
      return ControlDown();
      #endif
    }

    void        SetX( wxCoord x ) { m_x = x; }
    void        SetY( wxCoord y ) { m_y = y; }
    void        SetLeftDown( bool down )   { m_leftDown = down; }
    void        SetMiddleDown( bool down ) { m_middleDown = down; }
    void        SetRightDown( bool down )  { m_rightDown = down; }
    void        SetControlDown( bool down ) { m_controlDown = down; }
    void        SetShiftDown( bool down )   { m_shiftDown = down; }
    void        SetAltDown( bool down )     { m_altDown = down; }
    void        SetMetaDown( bool down )    { m_metaDown = down; }

  private:
    wxCoord     m_x;
    wxCoord     m_y;

    bool m_leftDown : 1;
    bool m_middleDown : 1;
    bool m_rightDown : 1;
    bool m_controlDown : 1;
    bool m_shiftDown : 1;
    bool m_altDown : 1;
    bool m_metaDown : 1;
};

wxMouseState wxGetMouseState();
long wxNewId();
void wxRegisterId( long id );
long wxGetCurrentId();

#endif // wxUSE_GUI

int wxHexToDec( const wxString& buf );
void wxDecToHex( int dec, wxChar *buf );
wxString wxDecToHex( int dec );

enum {
  wxEXEC_ASYNC    = 0,
  wxEXEC_SYNC     = 1,
  wxEXEC_NOHIDE   = 2,
  wxEXEC_MAKE_GROUP_LEADER = 4,
  wxEXEC_NODISABLE = 8
};

long wxExecute( wxChar **argv, int flags = wxEXEC_ASYNC, wxProcess *process = ( wxProcess * ) NULL );
long wxExecute( const wxString& command, int flags = wxEXEC_ASYNC, wxProcess *process = ( wxProcess * ) NULL );
long wxExecute( const wxString& command, wxArrayString& output, int flags = 0 );
long wxExecute( const wxString& command, wxArrayString& output, wxArrayString& error, int flags = 0 );

enum wxSignal {
  wxSIGNONE = 0,  // verify if the process exists under Unix
  wxSIGHUP,
  wxSIGINT,
  wxSIGQUIT,
  wxSIGILL,
  wxSIGTRAP,
  wxSIGABRT,
  wxSIGIOT = wxSIGABRT,   // another name
  wxSIGEMT,
  wxSIGFPE,
  wxSIGKILL,
  wxSIGBUS,
  wxSIGSEGV,
  wxSIGSYS,
  wxSIGPIPE,
  wxSIGALRM,
  wxSIGTERM
};

enum wxKillError {
  wxKILL_OK,              // no error
  wxKILL_BAD_SIGNAL,      // no such signal
  wxKILL_ACCESS_DENIED,   // permission denied
  wxKILL_NO_PROCESS,      // no such process
  wxKILL_ERROR            // another, unspecified error
};

enum wxKillFlags {
  wxKILL_NOCHILDREN = 0,  // don't kill children
  wxKILL_CHILDREN = 1     // kill children
};

enum wxShutdownFlags {
  wxSHUTDOWN_POWEROFF,    // power off the computer
  wxSHUTDOWN_REBOOT       // shutdown and reboot
};

bool wxShutdown( wxShutdownFlags wFlags );
int wxKill( long pid, wxSignal sig = wxSIGTERM, wxKillError *rc = NULL, int flags = wxKILL_NOCHILDREN );
bool wxShell( const wxString& command = wxEmptyString );
bool wxShell( const wxString& command, wxArrayString& output );
void wxSleep( int nSecs );
void wxMilliSleep( unsigned long milliseconds );
void wxMicroSleep( unsigned long microseconds );
wxDEPRECATED( void wxUsleep( unsigned long milliseconds ) );
unsigned long wxGetProcessId();
wxMemorySize wxGetFreeMemory();

#if wxUSE_ON_FATAL_EXCEPTION

bool wxHandleFatalExceptions( bool doit = true );

#endif // wxUSE_ON_FATAL_EXCEPTION

enum {
  wxBROWSER_NEW_WINDOW = 1
};

bool wxLaunchDefaultBrowser( const wxString& url, int flags = 0 );
bool wxGetEnv( const wxString& var, wxString *value );
bool wxSetEnv( const wxString& var, const wxChar *value );
inline bool wxUnsetEnv( const wxString& var ) { return wxSetEnv( var, NULL ); }
bool wxGetEmailAddress( wxChar *buf, int maxSize );
wxString wxGetEmailAddress();
bool wxGetHostName( wxChar *buf, int maxSize );
wxString wxGetHostName();
wxString wxGetFullHostName();
bool wxGetFullHostName( wxChar *buf, int maxSize );
bool wxGetUserId( wxChar *buf, int maxSize );
wxString wxGetUserId();
bool wxGetUserName( wxChar *buf, int maxSize );
wxString wxGetUserName();
wxString wxGetHomeDir();
const wxChar* wxGetHomeDir( wxString *pstr );

const wxMB2WXbuf wxGetUserHome( const wxString& user = wxEmptyString );

#if wxUSE_LONGLONG
typedef wxLongLong wxDiskspaceSize_t;
#else
typedef long wxDiskspaceSize_t;
#endif

bool wxGetDiskSpace( const wxString& path, wxDiskspaceSize_t *pTotal = NULL, wxDiskspaceSize_t *pFree = NULL );

#if wxUSE_GUI // GUI only things from now on

enum {
  wxStrip_Mnemonics = 1,
  wxStrip_Accel = 2,
  wxStrip_All = wxStrip_Mnemonics | wxStrip_Accel
};

wxString wxStripMenuCodes( const wxString& str, int flags = wxStrip_All );

wxDEPRECATED(
  wxChar* wxStripMenuCodes( const wxChar *in, wxChar *out = NULL )
);

#if wxUSE_ACCEL
class wxAcceleratorEntry;
wxDEPRECATED(
  wxAcceleratorEntry *wxGetAccelFromString( const wxString& label )
);
#endif // wxUSE_ACCEL

int wxFindMenuItemId( wxFrame *frame, const wxString& menuString, const wxString& itemString );
wxWindow* wxGenericFindWindowAtPoint( const wxPoint& pt );
wxWindow* wxFindWindowAtPoint( const wxPoint& pt );
wxWindow* wxFindWindowByLabel( const wxString& title, wxWindow *parent = ( wxWindow * ) NULL );
wxWindow* wxFindWindowByName( const wxString& name, wxWindow *parent = ( wxWindow * ) NULL );
bool wxSafeYield( wxWindow *win = NULL, bool onlyIfNeeded = false );
void wxEnableTopLevelWindows( bool enable = true );
bool wxCheckForInterrupt( wxWindow *wnd );
void wxFlushEvents();

class wxWindowDisabler {
  public:
    wxWindowDisabler( wxWindow *winToSkip = ( wxWindow * )NULL );
    ~wxWindowDisabler();

  private:
    wxWindowList *m_winDisabled;

    DECLARE_NO_COPY_CLASS( wxWindowDisabler )
};

void wxBeginBusyCursor( const wxCursor *cursor = wxHOURGLASS_CURSOR );
void wxEndBusyCursor();
bool wxIsBusy();

class wxBusyCursor {
  public:
    wxBusyCursor( const wxCursor* cursor = wxHOURGLASS_CURSOR ) { wxBeginBusyCursor( cursor ); }
    ~wxBusyCursor() { wxEndBusyCursor(); }
    static const wxCursor &GetStoredCursor();
    static const wxCursor GetBusyCursor();
};

bool wxWriteResource( const wxString& section, const wxString& entry, const wxString& value, const wxString& file = wxEmptyString );
bool wxWriteResource( const wxString& section, const wxString& entry, float value, const wxString& file = wxEmptyString );
bool wxWriteResource( const wxString& section, const wxString& entry, long value, const wxString& file = wxEmptyString );
bool wxWriteResource( const wxString& section, const wxString& entry, int value, const wxString& file = wxEmptyString );

bool wxGetResource( const wxString& section, const wxString& entry, wxChar **value, const wxString& file = wxEmptyString );
bool wxGetResource( const wxString& section, const wxString& entry, float *value, const wxString& file = wxEmptyString );
bool wxGetResource( const wxString& section, const wxString& entry, long *value, const wxString& file = wxEmptyString );
bool wxGetResource( const wxString& section, const wxString& entry, int *value, const wxString& file = wxEmptyString );

void wxGetMousePosition( int* x, int* y );
void *wxGetDisplay();

#ifdef __X__
WXDLLIMPEXP_CORE WXDisplay *wxGetDisplay();
WXDLLIMPEXP_CORE bool wxSetDisplay( const wxString& display_name );
WXDLLIMPEXP_CORE wxString wxGetDisplayName();
#endif // X or GTK+

#ifdef __X__

#ifdef __VMS__ // Xlib.h for VMS is not (yet) compatible with C++
// The resulting warnings are switched off here
#pragma message disable nosimpint
#endif
// #include <X11/Xlib.h>
#ifdef __VMS__
#pragma message enable nosimpint
#endif

#endif //__X__

#endif // wxUSE_GUI

#ifndef wx_YIELD_DECLARED
#define wx_YIELD_DECLARED

// Yield to other apps/messages
bool wxYield();

#endif // wx_YIELD_DECLARED

bool wxYieldIfNeeded();

#endif
